//: src/com/silvtar/sync/controller/Daemon.java
/* 
 * Created by 朴晟宁 <piaosn@gmail.com> on 4/21/2013. 
 * Copyright (c) 2013 朴晟宁. All rights reserved.
 * 
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program;
 * 
 * *********************************************************************
 * 
 * Modify History:
 * Date        Version    Description
 * 4/24/2013   0.1        Create The Class
 * 4/25/2013   0.1.1      It still a test-only class. But it can recieve
 *                        file from network now.
 */

package com.silvtar.sync.controller;

import java.net.InetAddress;
import java.net.Socket;
import java.util.ArrayList;

import com.silvtar.io.StdOut;
import com.silvtar.io.StreamToolkit;
import com.silvtar.net.Server;
import com.silvtar.net.ftp.FtpTransporter;
import com.silvtar.sync.model.SSAnalyzer;
import com.silvtar.sync.model.SSException;
import com.silvtar.sync.model.SSTree;

/**
 * 守护类。即本程序的服务器类
 * 
 * @author 朴晟宁/Silvtar
 * @author piaosn@gmail.com
 * @version 0.1.1
 */
public class Daemon extends Thread implements Server.Acceptor {

    static boolean running     = false;

    Server         server      = null;

    int            commandPort = 20681;

    String         localRoot   = "/Users/silvtar/Develop/FileSyncer/test/local";

    String         remoteRoot  = "/Users/silvtar/Develop/FileSyncer/test/remote";

    public void Daemon(int commandPort, String localRoot, String remoteRoot) {

        this.commandPort = commandPort;
        this.localRoot = localRoot;
        this.remoteRoot = remoteRoot;
    }

    /**
     * 开始运行守护程序, 本类要在被构造后调用这个函数才会开始起作用。
     */
    public void startDaemon() {

        if (!running) {
            start();
        } else {
            StdOut.println("Daemon is current running!");
        }
    }

    /**
     * 本函数不应由用户调用
     */
    @Override
    public void run() {

        running = true;
        server = new Server(this, commandPort);
        server.listen();

    }

    /**
     * 输出连接到本机的主机列表
     */
    public void printSocketList() {

        ArrayList<Socket> serverList = server.getSocketList();
        StdOut.println("SocketList's Length = " + serverList.size());
        for (int i = 0; i < serverList.size(); i++) {
            serverList.get(i);
            StdOut.println("No." + i + ": "
                    + serverList.get(i).getInetAddress().getHostName());
        }
    }

    /**
     * 将会被Server类回调的函数，当有发送文件的请求时，这个函数会被调用。
     */
    @Override
    public void accept(int identifier) {

        // 获取客户端socket
        Socket socket = server.getSocketList().get(identifier);

        // 获取流工具箱类
        StreamToolkit commander = new StreamToolkit(socket);

        // 获得客户端的IP地址
        InetAddress inetAddress = socket.getInetAddress();

        // 读取命令
        String command = commander.readUTF();

        // 判断命令
        if (command.equals("[Start Sync]")) {
            startSync(commander);
        }

    }

    /**
     * 开始同步进程
     * 
     * @return 是否同步成功
     */
    private boolean startSync(StreamToolkit commander) {

        commander.writeUTF("[Start Sync Recieved]");

        try {
            SSTree localTree = new SSTree(localRoot);
            SSTree remoteTree = (SSTree) commander.readObject();
            SSAnalyzer ssAnalyzer = new SSAnalyzer(localTree, remoteTree);
            ssAnalyzer.analyze();

            StdOut.println("\nlocalTree:\n");
            localTree.printFileTree();
            StdOut.println("\nremoteTree:\n");
            remoteTree.printFileTree();
            StdOut.println();

            if (commander.readUTF().equals("[FTP Already opened]")) {
                remoteRoot = commander.readUTF();
                FtpTransporter ftpTransporter = new FtpTransporter(ssAnalyzer,
                        localRoot, remoteRoot);
                ftpTransporter.startTransport();
            }

        } catch (SSException e) {

            e.printStackTrace();
        }

        return true;
    }
}
